package com.loeng.framework.mq.redis.core;

import com.loeng.framework.common.util.json.JsonUtils;
import com.loeng.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
import com.loeng.framework.mq.redis.core.message.AbstractRedisMessage;
import com.loeng.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;

/**
 * Redis MQ 操作模板类
 *
 * @author loeng zhuo
 */
@Slf4j
public class RedisMQTemplate {

    @Getter
    private final RedisTemplate<String, ?> redisTemplate;
    /**
     * 拦截器数组
     */
    @Getter
    private final List<RedisMessageInterceptor> interceptors;

    /**
     * 构造方法
     *
     * @param redisTemplate RedisTemplate
     * @param interceptors  拦截器数组
     */
    public RedisMQTemplate(RedisTemplate<String, ?> redisTemplate, List<RedisMessageInterceptor> interceptors) {
        this.redisTemplate = redisTemplate;
        this.interceptors = interceptors;
        this.interceptors.addAll(interceptors);
    }

    /**
     * 发送消息
     *
     * @param message 消息
     */
    public <T extends AbstractRedisChannelMessage> void send(T message) {
        try {
            sendMessageBefore(message);
            // 发布订阅模式 发送消息
            redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message));
        } catch (Exception e) {
            log.error("基于Redis模板发送消息失败error", e);
        } finally {
            sendMessageAfter(message);
        }
    }

    /**
     * 发送消息之前
     *
     * @param message 消息
     */
    private void sendMessageBefore(AbstractRedisMessage message) {
        // 正序
        interceptors.forEach(interceptor -> interceptor.sendMessageBefore(message));
    }

    /**
     * 发送消息之后
     *
     * @param message 消息
     */
    private void sendMessageAfter(AbstractRedisMessage message) {
        // 倒序
        for (int i = interceptors.size() - 1; i >= 0; i--) {
            interceptors.get(i).sendMessageAfter(message);
        }
    }

}
